/* 
 * Enterprise Library Extensions - DI + ORM.
 * Copyright (C) 2006
 *
 * GNU General Public License
 *
 * This program is free software; you can redistribute 
 * it and/or modify it under the terms of the GNU General Public License 
 * as published by the Free Software Foundation; either version 2 of the 
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful, but 
 * WITHOUT ANY WARRANTY; without even the implied warranty of 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
 * See the GNU General Public License for more details.
 */
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Reflection;

namespace ELE.EnterpriseLibrary.Common.Configuration.Design
{
  /// <summary>
  /// A windows form for selecting an assembly from a list.
  /// Works in conjuction with <see cref="AssemblySelectorEditor"/>.
  /// </summary>
  public partial class AssemblySelectorUI : Form
  {
    private const string AssemblyFileFilter = "Assemblies (*.exe;*.dll) | *.exe;*.dll";
    private OpenFileDialog openFileDialog = new OpenFileDialog();
    /// <summary>
    /// Default constructor initializes the window with the dlls in the current directory.
    /// </summary>
    public AssemblySelectorUI()
    {
      InitializeComponent();
      openFileDialog.Filter = AssemblyFileFilter;
      this.listBoxAssemblies.SelectionMode = SelectionMode.One;
      this.listBoxAssemblies.MultiColumn = true;
      this.listBoxAssemblies.BeginUpdate();
      string[] dlls = Directory.GetFiles(Environment.CurrentDirectory, "*.dll");
      foreach (string dll in dlls)
      {
        try
        {
          Assembly assembly = Assembly.LoadFrom(dll);
          this.listBoxAssemblies.Items.Add(assembly.FullName);
        }
        catch { }
      }
      this.listBoxAssemblies.EndUpdate();
    }

    private void buttonLoad_Click(object sender, EventArgs e)
    {

      DialogResult result = this.openFileDialog.ShowDialog();
      if (result == DialogResult.OK)
      {
        try
        {
          Assembly assembly = Assembly.LoadFrom(GetAssemblyName(this.openFileDialog.FileName));
          this.listBoxAssemblies.BeginUpdate();
          this.listBoxAssemblies.Items.Clear();
          this.listBoxAssemblies.Items.Add(assembly.FullName);
          this.listBoxAssemblies.EndUpdate();
        }
        catch (FileNotFoundException ex)
        {
          DisplayMessageBox("Failed to load Assembly " + this.openFileDialog.FileName + " : ex=" + ex.Message, string.Empty);
          return;
        }
        catch (BadImageFormatException ex)
        {
          DisplayMessageBox("Failed to load Assembly " + this.openFileDialog.FileName + " : ex=" + ex.Message, string.Empty);
          return;
        }
      }
    }

    private string GetAssemblyName(string fileName)
    {
      string assemblyFilename = fileName;
      try
      {
        string tempFilename = Path.GetTempFileName();
        File.Copy(this.openFileDialog.FileName, tempFilename, true);
        assemblyFilename = tempFilename;
      }
      catch (IOException)
      {
        // No big deal if we couldn't copy the file to temp directory.
        // We will use the original assembly file instead. The downside
        // of using the original assembly file is that you cannot 
        // update the assembly containing the type
        // until you close the Configuration Manager tool.
      }
      return assemblyFilename;
    }
    private void DisplayMessageBox(string message, string caption)
    {
      MessageBoxOptions options = (MessageBoxOptions)0;

      if (RightToLeft == RightToLeft.Yes)
      {
        options = MessageBoxOptions.RtlReading |
           MessageBoxOptions.RightAlign;
      }


      MessageBox.Show(message,
                          caption,
                          MessageBoxButtons.OK,
                          MessageBoxIcon.Information,
                          MessageBoxDefaultButton.Button1,
          options);

    }

    private void buttonSelect_Click(object sender, EventArgs e)
    {

      DialogResult = DialogResult.OK;
      Close();
    }
    /// <summary>
    /// The selected assembly
    /// </summary>
    public Assembly SelectedAssembly
    {
      get
      {
        return Assembly.Load(this.listBoxAssemblies.SelectedItem.ToString());
      }
    }

    private void buttonSelectFromGAC_Click(object sender, EventArgs e)
    {
      this.listBoxAssemblies.BeginUpdate();
      this.listBoxAssemblies.Items.Clear();
      string[] gacDirs = Directory.GetDirectories(Environment.GetEnvironmentVariable(@"WINDIR") + @"\assembly");
      foreach (string gacDir in gacDirs)
      {
        if (gacDir.Substring(gacDir.LastIndexOf(@"\") + 1).StartsWith("GAC"))
        {
          string[] dlls = Directory.GetFiles(gacDir, "*.dll", SearchOption.AllDirectories);
          foreach (string dll in dlls)
          {
            try
            {
              Assembly assembly = Assembly.LoadFrom(dll);
              this.listBoxAssemblies.Items.Add(assembly.FullName);
            }
            catch { }
          }
        }
      }
      this.listBoxAssemblies.EndUpdate();
    }
  }
}